<template>
    <div class="workflow-view">
      <!-- 加载动画 -->
      <div v-if="loading" class="loading-container">
        <div class="loading-animation">
          <div class="gear-container">
            <i class="fas fa-cog gear gear-1"></i>
            <i class="fas fa-cog gear gear-2"></i>
            <i class="fas fa-cog gear gear-3"></i>
          </div>
          <div class="progress">
            <div class="progress-bar" :style="{ width: loadingProgress + '%' }"></div>
          </div>
          <div class="loading-text">{{ loadingText }}</div>
        </div>
      </div>
  
      <template v-else>
        <div class="toolbar">
          <button class="add-node-btn" @click="addNewNode">
            <i class="fas fa-plus"></i>
            添加节点
          </button>
          <div class="edge-styles" v-if="selectedEdge">
            <div class="style-group">
              <label>线条样式：</label>
              <select v-model="selectedEdge.connector" @change="updateEdgeStyle">
                <option value="smooth">曲线</option>
                <option value="straight">直线</option>
                <option value="manhattan">折线</option>
              </select>
            </div>
            <div class="style-group">
              <label>起点样式：</label>
              <select v-model="selectedEdge.sourceMarker" @change="updateEdgeStyle">
                <option value="none">无</option>
                <option value="block">实心箭头</option>
                <option value="circle">圆形</option>
                <option value="diamond">菱形</option>
              </select>
            </div>
            <div class="style-group">
              <label>终点样式：</label>
              <select v-model="selectedEdge.targetMarker" @change="updateEdgeStyle">
                <option value="block">实心箭头</option>
                <option value="circle">圆形</option>
                <option value="diamond">菱形</option>
              </select>
            </div>
          </div>
          <button class="save-btn" @click="saveWorkflow">
            <i class="fas fa-save"></i>
            保存
          </button>
          <button class="clear-btn" @click="clearCanvas">
            <i class="fas fa-trash"></i>
            清空
          </button>
        </div>
  
        <!-- 工作流画布 -->
        <div class="workflow-canvas">
          <!-- 左侧组件栏 -->
          <div class="component-sidebar">
            <div class="component-group">
              <div class="group-title">基础节点</div>
              <div 
                class="component-item"
                draggable="true"
                @dragstart="onDragStart($event, 'rect')"
              >
                <div class="item-icon">
                  <i class="fas fa-square"></i>
                </div>
                <div class="item-content">
                  <div class="item-title">普通节点</div>
                  <div class="item-desc">基础流程节点</div>
                </div>
              </div>
              <div 
                class="component-item"
                draggable="true"
                @dragstart="onDragStart($event, 'circle')"
              >
                <div class="item-icon circle">
                  <i class="fas fa-circle"></i>
                </div>
                <div class="item-content">
                  <div class="item-title">圆形节点</div>
                  <div class="item-desc">开始/结束节点</div>
                </div>
              </div>
              <div 
                class="component-item"
                draggable="true"
                @dragstart="onDragStart($event, 'diamond')"
              >
                <div class="item-icon diamond">
                  <i class="fas fa-diamond"></i>
                </div>
                <div class="item-content">
                  <div class="item-title">菱形节点</div>
                  <div class="item-desc">条件判断节点</div>
                </div>
              </div>
            </div>
  
            <div class="component-group">
              <div class="group-title">AI组件</div>
              <div 
                class="component-item"
                draggable="true"
                @dragstart="onDragStart($event, 'ai-chat')"
              >
                <div class="item-icon ai-chat">
                  <i class="fas fa-robot"></i>
                </div>
                <div class="item-content">
                  <div class="item-title">AI对话</div>
                  <div class="item-desc">智能对话节点</div>
                </div>
              </div>
              <div 
                class="component-item"
                draggable="true"
                @dragstart="onDragStart($event, 'ai-image')"
              >
                <div class="item-icon ai-image">
                  <i class="fas fa-image"></i>
                </div>
                <div class="item-content">
                  <div class="item-title">AI绘图</div>
                  <div class="item-desc">智能绘图节点</div>
                </div>
              </div>
            </div>
          </div>
  
          <!-- 画布区域 -->
          <div class="canvas-container">
            <div ref="container" class="x6-container"></div>
          </div>
  
          <!-- 右侧属性面板 -->
          <div class="properties-panel" v-if="selectedNode">
            <div class="panel-header">
              <span class="panel-title">节点属性</span>
              <button class="close-btn" @click="selectedNode = null">
                <i class="fas fa-times"></i>
              </button>
            </div>
            <div class="panel-content">
              <div class="form-group">
                <label>名称</label>
                <input 
                  type="text" 
                  v-model="selectedNode.attrs.label.text"
                  @input="updateNodeLabel"
                >
              </div>
              <div class="form-group">
                <label>描述</label>
                <textarea 
                  v-model="selectedNode.description"
                  @input="updateNodeDescription"
                ></textarea>
              </div>
              <div class="form-group">
                <label>类型</label>
                <select v-model="selectedNode.type" @change="updateNodeType">
                  <option value="rect">普通节点</option>
                  <option value="circle">圆形节点</option>
                  <option value="diamond">菱形节点</option>
                  <option value="ai-chat">AI对话</option>
                  <option value="ai-image">AI绘图</option>
                </select>
              </div>
              
              <!-- AI组件特有配置 -->
              <template v-if="selectedNode.type === 'ai-chat' || selectedNode.type === 'ai-image'">
                <div class="form-group">
                  <label>AI模型</label>
                  <select v-model="selectedNode.aiModel">
                    <option value="gpt-4">GPT-4</option>
                    <option value="gpt-3.5">GPT-3.5</option>
                    <option value="claude-3">Claude 3</option>
                    <option value="gemini-pro">Gemini Pro</option>
                  </select>
                </div>
                <div class="form-group">
                  <label>系统提示词</label>
                  <textarea 
                    v-model="selectedNode.systemPrompt"
                    placeholder="设置AI的角色和行为..."
                    rows="4"
                  ></textarea>
                </div>
                <div class="form-group">
                  <label>温度</label>
                  <div class="slider-container">
                    <input 
                      type="range" 
                      v-model="selectedNode.temperature" 
                      min="0" 
                      max="2" 
                      step="0.1"
                    >
                    <span class="slider-value">{{ selectedNode.temperature }}</span>
                  </div>
                </div>
                <div class="form-group">
                  <label>最大长度</label>
                  <input 
                    type="number" 
                    v-model="selectedNode.maxTokens"
                    min="1"
                    max="4096"
                  >
                </div>
              </template>
            </div>
          </div>
        </div>
      </template>
    </div>
  </template>
  
  <script>
  import { Graph, Shape } from '@antv/x6'
  
  export default {
    name: 'WorkflowView',
    data() {
      return {
        loading: true,
        loadingProgress: 0,
        loadingText: '正在初始化工作流...',
        graph: null,
        selectedNode: null,
        selectedEdge: null
      }
    },
    mounted() {
      this.startLoading()
    },
    beforeUnmount() {
      if (this.graph) {
        this.graph.dispose()
      }
    },
    methods: {
      startLoading() {
        const steps = [
          { progress: 30, text: '正在加载组件库...' },
          { progress: 60, text: '正在准备画布...' },
          { progress: 90, text: '正在配置工作区...' },
          { progress: 100, text: '即将完成...' }
        ]
        
        let currentStep = 0
        const stepInterval = 800 // 每个步骤的时间间隔

        const progressTimer = setInterval(() => {
          if (currentStep < steps.length) {
            const { progress, text } = steps[currentStep]
            this.loadingProgress = progress
            this.loadingText = text
            currentStep++
          } else {
            clearInterval(progressTimer)
            // 先关闭加载动画，让 DOM 渲染完成
            this.loading = false
            // 使用 nextTick 确保 DOM 已更新
            this.$nextTick(() => {
              // 然后初始化图表
              this.initGraph()
              this.initDragAndDrop()
              this.initEvents()
            })
          }
        }, stepInterval)
      },
      initGraph() {
        // 添加容器检查
        if (!this.$refs.container) {
          console.error('Graph container not found')
          return
        }

        try {
          this.graph = new Graph({
            container: this.$refs.container,
            grid: true,
            mousewheel: {
              enabled: true,
              zoomAtMousePosition: true,
              modifiers: 'ctrl',
              minScale: 0.5,
              maxScale: 2,
            },
            connecting: {
              snap: true,
              allowBlank: false,
              allowLoop: false,
              highlight: true,
              connector: 'smooth',
              connectionPoint: 'boundary',
              router: {
                name: 'manhattan',
                args: {
                  padding: 1,
                },
              },
              validateConnection({ sourceView, targetView }) {
                return sourceView.id !== targetView.id
              },
            },
            highlighting: {
              magnetAvailable: {
                name: 'stroke',
                args: {
                  padding: 4,
                  attrs: {
                    strokeWidth: 4,
                    stroke: '#4f46e5',
                  },
                },
              },
            },
          })

          // 添加边的动画效果
          this.graph.on('edge:connected', ({ edge }) => {
            edge.attr({
              line: {
                strokeDasharray: '5 5',
                style: {
                  animation: 'flowing 30s linear infinite',
                },
              },
            })
          })
        } catch (error) {
          console.error('Failed to initialize graph:', error)
        }
      },
      initEvents() {
        this.graph.on('node:click', ({ node }) => {
          this.selectedNode = node
          this.selectedEdge = null
        })
  
        this.graph.on('edge:click', ({ edge }) => {
          this.selectedEdge = {
            edge,
            connector: edge.getConnector() || 'smooth',
            sourceMarker: edge.getSourceMarker() || 'none',
            targetMarker: edge.getTargetMarker() || 'block'
          }
          this.selectedNode = null
        })
  
        this.graph.on('blank:click', () => {
          this.selectedNode = null
          this.selectedEdge = null
        })
      },
      initDragAndDrop() {
        const container = this.$refs.container
        
        container.addEventListener('dragover', (e) => {
          e.preventDefault()
        })
  
        container.addEventListener('drop', (e) => {
          e.preventDefault()
          const nodeType = e.dataTransfer.getData('node-type')
          const position = this.graph.clientToLocal(e.clientX, e.clientY)
  
          this.addNode(nodeType, position)
        })
      },
      onDragStart(e, type) {
        e.dataTransfer.setData('node-type', type)
        e.dataTransfer.effectAllowed = 'copy'
      },
      addNode(type, position) {
        const baseConfig = {
          width: 180,
          height: 80,
          attrs: {
            body: {
              fill: '#fff',
              stroke: '#4f46e5',
              strokeWidth: 2,
            },
            label: {
              fill: '#333',
              fontSize: 14,
              refX: 40, // 文本右移，为图标留空间
            },
            icon: {
              width: 24,
              height: 24,
              refX: 12,
              refY: 12,
              'xlink:href': '',
            }
          },
          ports: {
            groups: {
              in: {
                position: 'left',
                attrs: {
                  circle: {
                    r: 4,
                    magnet: true,
                    stroke: '#4f46e5',
                    strokeWidth: 2,
                    fill: '#fff',
                  },
                },
              },
              out: {
                position: 'right',
                attrs: {
                  circle: {
                    r: 4,
                    magnet: true,
                    stroke: '#4f46e5',
                    strokeWidth: 2,
                    fill: '#fff',
                  },
                },
              },
            },
            items: [
              { group: 'in' },
              { group: 'out' },
            ],
          },
          ...position,
        }
  
        // 添加AI相关属性
        if (type === 'ai-chat' || type === 'ai-image') {
          baseConfig.aiModel = 'gpt-4'
          baseConfig.systemPrompt = ''
          baseConfig.temperature = 0.7
          baseConfig.maxTokens = 2000
        }
  
        let nodeConfig = { ...baseConfig }
  
        switch (type) {
          case 'rect':
            nodeConfig.shape = 'rect'
            nodeConfig.attrs.body.rx = 6
            nodeConfig.attrs.body.ry = 6
            nodeConfig.attrs.label.text = '普通节点'
            nodeConfig.attrs.icon['xlink:href'] = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#4f46e5" d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></svg>')
            break
  
          case 'circle':
            nodeConfig.shape = 'circle'
            nodeConfig.width = 80
            nodeConfig.height = 80
            nodeConfig.attrs.label.text = '圆形'
            nodeConfig.attrs.icon['xlink:href'] = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#4f46e5"/></svg>')
            break
  
          case 'diamond':
            nodeConfig.shape = 'polygon'
            nodeConfig.width = 100
            nodeConfig.height = 100
            nodeConfig.attrs.body.refPoints = '0,50 50,0 100,50 50,100'
            nodeConfig.attrs.label.text = '菱形'
            nodeConfig.attrs.icon['xlink:href'] = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#4f46e5" d="M12 2L2 12l10 10 10-10L12 2z"/></svg>')
            break
  
          case 'ai-chat':
            nodeConfig.shape = 'rect'
            nodeConfig.attrs.body.rx = 6
            nodeConfig.attrs.body.ry = 6
            nodeConfig.attrs.label.text = 'AI对话'
            nodeConfig.attrs.body.stroke = '#10b981'
            nodeConfig.attrs.icon['xlink:href'] = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#10b981" d="M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z"/></svg>')
            break
  
          case 'ai-image':
            nodeConfig.shape = 'rect'
            nodeConfig.attrs.body.rx = 6
            nodeConfig.attrs.body.ry = 6
            nodeConfig.attrs.label.text = 'AI绘图'
            nodeConfig.attrs.body.stroke = '#8b5cf6'
            nodeConfig.attrs.icon['xlink:href'] = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#8b5cf6" d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>')
            break
        }
  
        const node = this.graph.addNode(nodeConfig)
        this.graph.centerCell(node)
      },
      updateNodeLabel() {
        if (this.selectedNode) {
          this.graph.trigger('node:change', { node: this.selectedNode })
        }
      },
      updateNodeDescription() {
        if (this.selectedNode) {
          this.graph.trigger('node:change', { node: this.selectedNode })
        }
      },
      updateNodeType() {
        if (this.selectedNode) {
          const { position, size } = this.selectedNode.getBBox()
          this.selectedNode.remove()
          this.addNode(this.selectedNode.type, position)
        }
      },
      addNewNode() {
        this.addNode('rect', {
          x: Math.random() * (this.graph.getGraphArea().width - 200) + 100,
          y: Math.random() * (this.graph.getGraphArea().height - 100) + 50,
        })
      },
      saveWorkflow() {
        const data = this.graph.toJSON()
        console.log('Workflow data:', data)
        // TODO: 保存到后端
      },
      clearCanvas() {
        if (confirm('确定要清空画布吗？')) {
          this.graph.clearCells()
        }
      },
      updateEdgeStyle() {
        if (!this.selectedEdge) return

        const { edge, connector, sourceMarker, targetMarker } = this.selectedEdge
        
        edge.setConnector(connector)
        edge.setSourceMarker(sourceMarker)
        edge.setTargetMarker(targetMarker)

        // 重新应用动画
        edge.attr({
          line: {
            strokeDasharray: '5 5',
            style: {
              animation: 'flowing 30s linear infinite',
            },
          },
        })
      }
    }
  }
  </script>
  
  <style scoped>
  .workflow-view {
    display: flex;
    flex-direction: column;
    margin-top: 50px;
    height: 100vh;
    background: #f8fafc;
  }
  
  /* 加载动画 */
  .loading-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: #f8fafc;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
  }
  
  .loading-animation {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
  }
  
  .gear-container {
    position: relative;
    width: 120px;
    height: 120px;
  }
  
  .gear {
    position: absolute;
    color: #4f46e5;
    animation: spin 4s linear infinite;
    filter: drop-shadow(0 0 2px rgba(79, 70, 229, 0.3));
  }
  
  .gear-1 {
    font-size: 60px;
    top: 0;
    left: 30px;
  }
  
  .gear-2 {
    font-size: 40px;
    top: 50px;
    left: 0;
    animation-direction: reverse;
  }
  
  .gear-3 {
    font-size: 40px;
    top: 50px;
    right: 0;
    animation-direction: reverse;
  }
  
  @keyframes spin {
    100% {
      transform: rotate(360deg);
    }
  }
  
  .progress {
    width: 240px;
    height: 4px;
    background: #e2e8f0;
    border-radius: 2px;
    overflow: hidden;
  }
  
  .progress-bar {
    height: 100%;
    background: #4f46e5;
    border-radius: 2px;
    transition: width 0.3s ease;
    position: relative;
    overflow: hidden;
  }
  
  .progress-bar::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(
      90deg,
      transparent,
      rgba(255, 255, 255, 0.4),
      transparent
    );
    animation: shimmer 1.5s infinite;
  }
  
  @keyframes shimmer {
    0% {
      transform: translateX(-100%);
    }
    100% {
      transform: translateX(100%);
    }
  }
  
  .loading-text {
    color: #64748b;
    font-size: 14px;
    min-width: 160px;
    text-align: center;
  }
  
  .toolbar {
    padding: 16px;
    background: white;
    border-bottom: 1px solid #e2e8f0;
    display: flex;
    gap: 12px;
  }
  
  .toolbar button {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 500;
    transition: all 0.2s ease;
  }
  
  .add-node-btn {
    background: #4f46e5;
    color: white;
  }
  
  .add-node-btn:hover {
    background: #4338ca;
  }
  
  .save-btn {
    background: #10b981;
    color: white;
  }
  
  .save-btn:hover {
    background: #059669;
  }
  
  .clear-btn {
    background: #ef4444;
    color: white;
  }
  
  .clear-btn:hover {
    background: #dc2626;
  }
  
  .workflow-canvas {
    flex: 1;
    display: flex;
    background: #fff;
    overflow: hidden;
  }
  
  .component-sidebar {
    width: 240px;
    border-right: 1px solid #e2e8f0;
    background: #fff;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 20px;
  }
  
  .component-group {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  
  .group-title {
    font-size: 14px;
    color: #64748b;
    margin-bottom: 4px;
    font-weight: 500;
  }
  
  .component-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    cursor: grab;
    user-select: none;
    transition: all 0.2s ease;
  }
  
  .component-item:hover {
    border-color: #4f46e5;
    background: #eef2ff;
  }
  
  .item-icon {
    width: 40px;
    height: 40px;
    background: #eef2ff;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #4f46e5;
    font-size: 20px;
    flex-shrink: 0;
  }
  
  .item-icon.circle {
    border-radius: 50%;
  }
  
  .item-icon.diamond {
    transform: rotate(45deg);
  }
  
  .item-icon.diamond i {
    transform: rotate(-45deg);
  }
  
  .item-icon.ai-chat {
    background: #dcfce7;
    color: #10b981;
  }
  
  .item-icon.ai-image {
    background: #f3e8ff;
    color: #8b5cf6;
  }
  
  .item-content {
    flex: 1;
    min-width: 0;
  }
  
  .item-title {
    font-weight: 500;
    color: #334155;
    margin-bottom: 4px;
  }
  
  .item-desc {
    font-size: 12px;
    color: #64748b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  
  .canvas-container {
    flex: 1;
    position: relative;
    overflow: hidden;
  }
  
  .x6-container {
    width: 100%;
    height: 100%;
  }
  
  .properties-panel {
    width: 280px;
    background: white;
    border-left: 1px solid #e2e8f0;
    display: flex;
    flex-direction: column;
  }
  
  .panel-header {
    padding: 16px;
    border-bottom: 1px solid #e2e8f0;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .panel-title {
    font-weight: 500;
    color: #334155;
  }
  
  .close-btn {
    background: none;
    border: none;
    color: #64748b;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    transition: all 0.2s ease;
  }
  
  .close-btn:hover {
    background: #f1f5f9;
    color: #334155;
  }
  
  .panel-content {
    padding: 16px;
    overflow-y: auto;
  }
  
  .form-group {
    margin-bottom: 16px;
  }
  
  .form-group label {
    display: block;
    margin-bottom: 8px;
    color: #64748b;
    font-size: 14px;
  }
  
  .form-group input,
  .form-group textarea,
  .form-group select {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #e2e8f0;
    border-radius: 6px;
    background: #f8fafc;
    color: #334155;
    font-size: 14px;
    transition: all 0.2s ease;
  }
  
  .form-group input:focus,
  .form-group textarea:focus,
  .form-group select:focus {
    outline: none;
    border-color: #4f46e5;
    box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.1);
  }
  
  .form-group textarea {
    min-height: 100px;
    resize: vertical;
  }
  
  :deep(.x6-node) {
    cursor: move;
  }
  
  :deep(.x6-port) {
    cursor: crosshair;
  }
  
  :deep(.x6-edge) {
    cursor: pointer;
  }
  
  :deep(.x6-edge:hover) path {
    stroke: #4f46e5;
    stroke-width: 2px;
  }
  
  /* 添加新样式 */
  .edge-styles {
    display: flex;
    gap: 16px;
    align-items: center;
  }
  
  .style-group {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  
  .style-group label {
    color: #64748b;
    font-size: 14px;
  }
  
  .style-group select {
    padding: 4px 8px;
    border: 1px solid #e2e8f0;
    border-radius: 4px;
    background: white;
    color: #334155;
    font-size: 14px;
  }
  
  .slider-container {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  
  .slider-container input[type="range"] {
    flex: 1;
    height: 4px;
    background: #e2e8f0;
    border-radius: 2px;
    outline: none;
  }
  
  .slider-container input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 16px;
    height: 16px;
    background: #4f46e5;
    border-radius: 50%;
    cursor: pointer;
  }
  
  .slider-value {
    min-width: 40px;
    text-align: right;
    color: #64748b;
    font-size: 14px;
  }
  
  /* 添加连线动画 */
  @keyframes flowing {
    from {
      stroke-dashoffset: 100;
    }
    to {
      stroke-dashoffset: 0;
    }
  }
  
  :deep(.x6-edge) path {
    stroke-dasharray: 5 5;
    animation: flowing 30s linear infinite;
  }
  
  :deep(.x6-edge.x6-edge-selected) path {
    stroke: #4f46e5;
    stroke-width: 2px;
  }
  </style> 